import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, accuracy_score
from sklearn.ensemble import RandomForestClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from xgboost import XGBClassifier
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei']  # 'SimHei' 是黑体的意思
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
# 加载数据
data = pd.read_excel('C:/Users/Administrator/Downloads/信用卡精准营销模型.xlsx')

# 检查缺失值
print(data.isnull().sum())

# 检查重复值
print(data.duplicated().sum())

# 检查异常值
print(data.describe())

# 计算消费收入比(已有)
data['消费收入比'] = data['月消费（元）'] / data['月收入（元）']

# 分箱处理年龄
data['年龄分组'] = pd.cut(data['年龄'], bins=[20,25,30,35,40], labels=['20-25','26-30','31-35','36-40'])

# 创建收入水平特征
data['收入水平'] = pd.qcut(data['月收入（元）'], q=4, labels=['低','中低','中高','高'])

# 保存年龄列用于分析后再删除
data['原始年龄'] = data['年龄']

# 将分类变量转换为哑变量
data = pd.get_dummies(data, columns=['年龄分组', '收入水平'], drop_first=True)

# 响应率
response_rate = data['响应'].value_counts(normalize=True)
print(f"响应率: {response_rate[1]:.2%}")

# 响应率与性别的关系
gender_response = data.groupby('性别')['响应'].mean()
print("\n性别响应率:")
print(gender_response)

# 响应率与年龄的关系 (使用保存的原始年龄列)
age_response = data.groupby(pd.cut(data['原始年龄'], bins=[20,25,30,35,40]))['响应'].mean()
print("\n年龄组响应率:")
print(age_response)

# 计算相关系数
corr_matrix = data.corr()

# 可视化相关系数矩阵
plt.figure(figsize=(12,8))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('特征相关性矩阵')
plt.show()

# 响应与各特征的分布
fig, axes = plt.subplots(2, 2, figsize=(12,10))
sns.boxplot(x='响应', y='月消费（元）', data=data, ax=axes[0,0])
sns.boxplot(x='响应', y='消费收入比', data=data, ax=axes[0,1])
sns.countplot(x='性别', hue='响应', data=data, ax=axes[1,0])
sns.countplot(x=pd.cut(data['原始年龄'], bins=[20,25,30,35,40]), hue='响应', data=data, ax=axes[1,1])
plt.tight_layout()
plt.show()

# 现在可以删除原始列
data.drop(['年龄', '月收入（元）', '原始年龄'], axis=1, inplace=True)

# 分割特征和目标变量
X = data.drop('响应', axis=1)
y = data['响应']

# 分割训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)

# 标准化数值特征
scaler = StandardScaler()
num_cols = ['月消费（元）', '消费收入比']
X_train[num_cols] = scaler.fit_transform(X_train[num_cols])
X_test[num_cols] = scaler.transform(X_test[num_cols])

# 初始化模型
models = {
    'Logistic Regression': LogisticRegression(max_iter=1000),
    'Random Forest': RandomForestClassifier(n_estimators=100, random_state=42),
    'SVM': SVC(probability=True, random_state=42),
    'XGBoost': XGBClassifier(random_state=42)
}

# 训练并评估模型
results = {}
for name, model in models.items():
    model.fit(X_train, y_train)
    y_pred = model.predict(X_test)
    y_prob = model.predict_proba(X_test)[:, 1]

    # 存储结果
    results[name] = {
        'Accuracy': accuracy_score(y_test, y_pred),
        'ROC AUC': roc_auc_score(y_test, y_prob),
        'Classification Report': classification_report(y_test, y_pred),
        'Confusion Matrix': confusion_matrix(y_test, y_pred)
    }

    # 打印结果
    print(f"\n{name} 模型结果:")
    print(f"准确率: {results[name]['Accuracy']:.4f}")
    print(f"ROC AUC: {results[name]['ROC AUC']:.4f}")
    print("分类报告:")
    print(results[name]['Classification Report'])

    # 绘制混淆矩阵
    plt.figure(figsize=(6, 4))
    sns.heatmap(results[name]['Confusion Matrix'], annot=True, fmt='d', cmap='Blues')
    plt.title(f'{name} 混淆矩阵')
    plt.xlabel('预测值')
    plt.ylabel('真实值')
    plt.show()

# 比较模型性能
model_comparison = pd.DataFrame({
    'Model': list(results.keys()),
    'Accuracy': [results[name]['Accuracy'] for name in results],
    'ROC AUC': [results[name]['ROC AUC'] for name in results]
}).sort_values(by='ROC AUC', ascending=False)

print("\n模型性能比较:")
print(model_comparison)

# 可视化模型比较
plt.figure(figsize=(10, 6))
model_comparison.set_index('Model').plot(kind='bar', rot=45)
plt.title('模型性能比较')
plt.ylabel('分数')
plt.legend(loc='lower right')
plt.tight_layout()
plt.show()

# 使用最佳模型
best_model = RandomForestClassifier(n_estimators=100, random_state=42)
best_model.fit(X_train, y_train)

# 获取特征重要性
feature_importance = pd.DataFrame({
    'Feature': X.columns,
    'Importance': best_model.feature_importances_
}).sort_values(by='Importance', ascending=False)

# 可视化特征重要性
plt.figure(figsize=(10, 6))
sns.barplot(x='Importance', y='Feature', data=feature_importance)
plt.title('特征重要性排序')
plt.tight_layout()
plt.show()